﻿using System;
using System.Runtime.Serialization;

namespace Aeon.Emulator.RuntimeExceptions
{
    /// <summary>
    /// Represents an exception that occurred in an emulated system.
    /// </summary>
    [Serializable]
    public class EmulatedException : Exception
    {
        #region Constructors
        /// <summary>
        /// Initializes a new instance of the EmulatedException class.
        /// </summary>
        public EmulatedException()
        {
        }
        /// <summary>
        /// Initializes a new instance of the EmulatedException class.
        /// </summary>
        /// <param name="interrupt">Interupt to be raised on the emulated system.</param>
        public EmulatedException(int interrupt)
        {
            this.interrupt = interrupt;
        }
        /// <summary>
        /// Initializes a new instance of the EmulatedException class.
        /// </summary>
        /// <param name="message">Message describing the exception.</param>
        public EmulatedException(string message)
            : base(message)
        {
        }
        /// <summary>
        /// Initializes a new instance of the EmulatedException class.
        /// </summary>
        /// <param name="interrupt">Interupt to be raised on the emulated system.</param>
        /// <param name="message">Message describing the exception.</param>
        public EmulatedException(int interrupt, string message)
            : base(message)
        {
            this.interrupt = interrupt;
        }
        /// <summary>
        /// Initializes a new instance of the EmulatedException class.
        /// </summary>
        /// <param name="message">Message describing the exception.</param>
        /// <param name="inner">Exception which caused this exception.</param>
        public EmulatedException(string message, Exception inner)
            : base(message, inner)
        {
        }
        /// <summary>
        /// Initializes a new instance of the EmulatedException class.
        /// </summary>
        /// <param name="interrupt">Interupt to be raised on the emulated system.</param>
        /// <param name="message">Message describing the exception.</param>
        /// <param name="inner">Exception which caused this exception.</param>
        public EmulatedException(int interrupt, string message, Exception inner)
            : base(message, inner)
        {
            this.interrupt = interrupt;
        }
        /// <summary>
        /// Initializes a new instance of the EmulatedException class.
        /// </summary>
        /// <param name="info">Information for serialization.</param>
        /// <param name="context">Context information for serialization.</param>
        protected EmulatedException(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            this.interrupt = info.GetInt32("interrupt");
        }
        #endregion

        #region Public Properties
        /// <summary>
        /// Gets the interrupt that should be raised on the emulated
        /// system as a result of the exception.
        /// </summary>
        public virtual int Interrupt
        {
            get { return this.interrupt; }
        }
        /// <summary>
        /// Gets the optional error code for the interrupt.
        /// </summary>
        public virtual int? ErrorCode
        {
            get { return null; }
        }
        #endregion

        #region Internal Methods
        /// <summary>
        /// Invoked when the exception is raised by the emulator.
        /// </summary>
        /// <param name="vm">VirtualMachine instance which is raising the exception.</param>
        internal virtual void OnRaised(VirtualMachine vm)
        {
        }
        #endregion

        #region Private Fields
        /// <summary>
        /// Interrupt that should be raised on the emulated system.
        /// </summary>
        private int interrupt = -1;
        #endregion
    }
}
